--------------------------------------------------------------------------
-- $File: //scripts/entities/items/Item.lua $
-- $Revision$
-- $Date$
-- $Author$
--
-- $Id$
--------------------------------------------------------------------------
-- This file is maintained as part of the SSM AEGIS project. All additions
-- are the sole work of their authors to which all copyright and ownership
-- resides. However, each author grants license for the use of his or her
-- work to be a part of the SSM AEGIS project.
--
--  (C), Daniel 'Rod-Serling' Phelps, 2008
--  (C), Terry 'Charlie' Reinert, 2008
--------------------------------------------------------------------------
--  This work is based off of:
--	(C), Ralf 'Hawkeye' Ullrich, 2008
--------------------------------------------------------------------------
Item = {
	Properties={
		bPickable = 0,
		bPhysics = 0,
		bMounted = 0,
		bUsable = 0,
		HitPoints = 0,
		soclasses_SmartObjectClass = "",
		initialSetup = "",
	},
	
	Client = {},
	Server = {},
	
	Editor={
		Icon = "Item.bmp",
		IconOnTop=1,
	},
}


-- =============================================================================
-- Function: Item:OnPropertyChange
--
-- This function resets the item properties and then calls
-- OnReset for the parent.
-- =============================================================================
function Item:OnPropertyChange()
	self.item:Reset();
	
	if (self.OnReset) then
		self:OnReset();
	end
end

-- =============================================================================
-- Function: Item:IsUsable
--
-- This function determines whether the item is usable
-- or not. 
--
-- \param[in] user
-- The entity of the player wanting to use the item.
--
-- \return
-- 1 if the player can use the item; 0 if not.
-- =============================================================================
function Item:IsUsable(user)
	local mp = System.IsMultiplayer();
	if(mp and mp~=0 and (self.item:CanPickUp(user.id) or self.item:CanUse(user.id))) then
		return 1;
	elseif (((not mp) or mp==0) and self.item:CanUse(user.id)) then
		return 1;
	else
		return 0;
	end
end


-- =============================================================================
-- Function: Item:GetUsableMessage
--
-- This function gets a message string that is displayed to
-- a player whenever the player is near the item and looking
-- at it. 
--
-- \return
-- If the item is mounted then the string contained in the
-- localization file for "@use_mounted" is returned. If the
-- item is not mounted then a blank string is returned.
-- =============================================================================
function Item:GetUsableMessage()
	if (self.item:IsMounted()) then
		return "@use_mounted";
	else
		return "";
	end
end


-- =============================================================================
-- Function: Item:OnUsed
--
-- This function is called whenever the item is used.
--
-- \param[in] user
-- The entity of the player using the item.
--
-- \return
-- The result from the self.item:OnUsed function.
-- =============================================================================
function Item:OnUsed(user)
	return self.item:OnUsed(user.id);
end

-- =============================================================================
-- Function: Item:GetHealth
--
-- This function gets the health of the item.
--
-- \return
-- The health of the item.
-- =============================================================================
function Item:GetHealth()
	return self.item:GetHealth();
end

-- =============================================================================
-- Function: Item:GetMaxHealth
--
-- This function gets the maximum health of the item.
--
-- \return
-- The maximum health of the item.
-- =============================================================================
function Item:GetMaxHealth()
	return self.item:GetMaxHealth();
end


-- =============================================================================
-- Function: Item:OnFreeze
--
-- This function is called when an item is froze.
--
-- \param[in] shooterId
-- The ID of the attacking player.
--
-- \param[unused] weaponId
-- The ID of the attackers weapon.
--
-- \param[unused] value
-- 
--
-- \return
-- True if in single player mode or the attacker is not on
-- the same team as this item.
-- =============================================================================
function Item:OnFreeze(shooterId, weaponId, value)
	if ((not g_gameRules:IsMultiplayer()) or g_gameRules.game:GetTeam(shooterId)~=g_gameRules.game:GetTeam(self.id)) then
		return true;
	end
	return false;
end

-- =============================================================================
-- Function: Item.Server:OnHit
--
-- This function is the event handler for when the item is
-- hit. It checks to see if the item is destroyed based on
-- its hit points and damage amount.
--
-- Note: This looks to be specific to turrets only. 
--
-- \param[in] hit
-- Structure containing the hit parameters for the hit.
-- =============================================================================
function Item.Server:OnHit(hit)
	local explosionOnly=tonumber(self.Properties.bExplosionOnly or 0)~=0;
	local hitpoints = self.Properties.HitPoints;

	if (hitpoints and (hitpoints > 0)) then
		local destroyed=self.item:IsDestroyed()
		if (hit.type=="repair") then
			self.item:OnHit(hit);
		elseif ((not explosionOnly) or (hit.explosion)) then
			if ((not g_gameRules:IsMultiplayer()) or g_gameRules.game:GetTeam(hit.shooterId)~=g_gameRules.game:GetTeam(self.id)) then	
				--patch1 hack: to compensate for decreased law damage
				--should have some kind of multiplier table per damage type
				--this will suffice for the time being
				if (hit.type=="law_rocket") then
					hit.damage=hit.damage*2.0;
				end

				self.item:OnHit(hit);
				if (not destroyed) then
					if (hit.damage>0) then
						if (g_gameRules.Server.OnTurretHit) then
							g_gameRules.Server.OnTurretHit(g_gameRules, self, hit);
						end
					end
				
					if (self.item:IsDestroyed()) then
						if(self.FlowEvents and self.FlowEvents.Outputs.Destroyed)then
							self:ActivateOutput("Destroyed",1);
						end
					end
				end
			end
		end
	end
end

-- =============================================================================
-- Function: Item.Server:OnShattered
--
-- This function is the event handler for the OnShattered
-- event for an item. This is a simple wrapper function for
-- the GameRules.Server.OnTurretHit function.
--
-- \param[in] hit
-- Structure containing the hit parameters for the hit.
--
-- \return
-- The result from the GameRules.Server.OnTurretHit function.
-- =============================================================================
function Item.Server:OnShattered(hit)
	g_gameRules.Server.OnTurretHit(g_gameRules, self, hit);
end

-- =============================================================================
-- Function: Item.Event_Hide
--
-- This function sets the Hide property on the item.
-- =============================================================================
function Item:Event_Hide()
	self:Hide(1);
	self:ActivateOutput( "Hide", true );
end

-- =============================================================================
-- Function: Item.Event_UnHide
--
-- This function clears the Hide property on the item.
-- =============================================================================
function Item:Event_UnHide()
	self:Hide(0);
	self:ActivateOutput( "UnHide", true );
end


Item.FlowEvents =
{
	Inputs =
	{
		Hide = { Item.Event_Hide, "bool" },
		UnHide = { Item.Event_UnHide, "bool" },
	},
	Outputs =
	{
		Hide = "bool",
		UnHide = "bool",
	},
}

-- =============================================================================
-- Function: MakeRespawnable
--
-- This function makes the item respawnable by setting the
-- nTimer property to 30 seconds. 
--
-- \param[in] entity
-- The entity to make respawnable.
-- =============================================================================
function MakeRespawnable(entity)
	if (entity.Properties) then
		entity.Properties.Respawn={
			nTimer=30,
			bUnique=0,
			bRespawn=0,
		};
	end
end


-- =============================================================================
-- Function: CreateItemTable
--
-- This function creates the item table for the item.
--
-- \param[in] name
-- The name of the item this table is being created for.
-- =============================================================================
function CreateItemTable(name)
	if (not _G[name]) then
		_G[name] = new(Item);
	end
	MakeRespawnable(_G[name]);
end


----------------------------------------------------------------------------------------------------
CreateItemTable("CustomAmmoPickup");
CustomAmmoPickup.Properties.objModel="";
CustomAmmoPickup.Properties.bMounted=nil;
CustomAmmoPickup.Properties.HitPoints=nil;
CustomAmmoPickup.Properties.AmmoName="bullet";
CustomAmmoPickup.Properties.Count=30;


----------------------------------------------------------------------------------------------------
CreateItemTable("ShiTen");

ShiTen.Properties.bMounted=1;
ShiTen.Properties.bUsable=1;
ShiTen.Properties.MountedLimits = {
			pitchMin = -22,
			pitchMax = 60,
			yaw = 70,
			};


-- =============================================================================
-- Function: ShiTen:OnReset
--
-- This function resets the parameters of the mounted ShiTen.
-- =============================================================================
function ShiTen:OnReset()
	self.item:SetMountedAngleLimits( self.Properties.MountedLimits.pitchMin,
									 self.Properties.MountedLimits.pitchMax,
									 self.Properties.MountedLimits.yaw	);
end

-- =============================================================================
-- Function: ShiTen:OnSpawn
--
-- This function is the event handler for the spawn event of
-- a mounted ShiTen item. It simply resets its parameters.
-- =============================================================================
function ShiTen:OnSpawn()
	self:OnReset();
end


-- =============================================================================
-- Function: ShiTen:OnUsed
--
-- This function is the event handler for the OnUsed event
-- for the mounted ShiTen. If the user is a player then the
-- Item.OnUsed function is called. If the user is not a player
-- then the AI signal is raised to the AI engine to handle the
-- AI operation of the mounted ShiTen.
--
-- \param[in] user
-- The entity of the user.
-- =============================================================================
function ShiTen:OnUsed(user)
	if (user.actor:IsPlayer()) then
		Item.OnUsed(self, user);
	else
		g_SignalData.id = self.id;
		AI.Signal(SIGNALFILTER_SENDER,0,"USE_MOUNTED_WEAPON_INIT",user.id,g_SignalData);
	end
end

-- =============================================================================
-- Function: CreateTurret
--
-- This function creates a turret of the specified class type
-- and sets all its parameters to default values. 
--
-- \param[in] name
-- The class for the turret entity being created.
-- =============================================================================
function CreateTurret(name)
	CreateItemTable(name);	
	
	local Turret = _G[name];
	
	Turret.Properties.species = 0;	
	Turret.Properties.teamName = "";
	Turret.Properties.GunTurret = 
	{
		bSurveillance = 1,
		bVehiclesOnly = 0,
		bAirVehiclesOnly = 0,
		bEnabled = 1,
		bSearching = 0,
		bSearchOnly = 0,
		MGRange = 50,
		RocketRange = 50,
		TACDetectRange = 300,
		TurnSpeed = 1.5,
		SearchSpeed = 0.5,
		UpdateTargetTime = 2.0,
		AbandonTargetTime = 0.5,
		TACCheckTime = 0.2,
		YawRange = 360,
		MinPitch = -45,
		MaxPitch = 45,
		AimTolerance = 20,
		Prediction = 1,
		BurstTime = 0.0,
		BurstPause = 0.0,
		SweepTime = 0.0,
		LightFOV = 0.0,
		bFindCloaked = 1,
		bExplosionOnly = 0,
	};
	
	Turret.Server.OnInit = function(self)
		self:OnReset();
	end;
	
	Turret.OnReset = function(self)
		local teamId=g_gameRules.game:GetTeamId(self.Properties.teamName) or 0;
		g_gameRules.game:SetTeam(teamId, self.id);
	end;

	Turret.Properties.objModel="";
	Turret.Properties.objBarrel="";
  Turret.Properties.objBase="";
  Turret.Properties.objDestroyed="";
  
  Turret.Properties.bUsable=nil;
  Turret.Properties.bPickable=nil;
		
  Turret.Event_EnableTurret = function(self)
    self.Properties.GunTurret.bEnabled=1; 
  end;  
  Turret.Event_DisableTurret = function(self)
    self.Properties.GunTurret.bEnabled=0; 
  end;
  
  Turret.FlowEvents.Inputs.EnableTurret = { Turret.Event_EnableTurret, "bool" };
  Turret.FlowEvents.Inputs.DisableTurret = { Turret.Event_DisableTurret, "bool" };  
  Turret.FlowEvents.Outputs.Destroyed =  "bool";
  
  return Turret;
  
end

CreateTurret("AlienTurret");
CreateTurret("WarriorMOARTurret");
CreateTurret("AutoTurret").Properties.bExplosionOnly=1;
CreateTurret("AutoTurretAA").Properties.bExplosionOnly=1;

-- =============================================================================
-- Function: AutoTurret.Server:OnHit
--
-- This function is the event handler for when an AutoTurret
-- when it is hit. If the useVulnerableTurretsFeature is on
-- and it is a multiplayer game then the turret takes damage.
-- If single player or turrets are invulnerable then this
-- function exits without doing anything. 
--
-- \param[in] hit
-- Structure containing the parameters for the hit.
-- =============================================================================
function AutoTurret.Server:OnHit(hit)
	if(g_gameRules:IsMultiplayer() and (not XCfgVar or not XCfgVar.useVulnerableTurretsFeature))then
		return;
	else
		Item.Server.OnHit(self, hit);
	end;
end

-- =============================================================================
-- Function: AutoTurretAA.Server:OnHit
--
-- This function is the event handler for when an AutoTurretAA
-- when it is hit. If the useVulnerableTurretsFeature is on
-- and it is a multiplayer game then the turret takes damage.
-- If single player or turrets are invulnerable then this
-- function exits without doing anything. 
--
-- \param[in] hit
-- Structure containing the parameters for the hit.
-- =============================================================================
function AutoTurretAA.Server:OnHit(hit)
	if(g_gameRules:IsMultiplayer() and (not XCfgVar or not XCfgVar.useVulnerableTurretsFeature))then
		return;
	else
		Item.Server.OnHit(self, hit);
	end;
end

-- =============================================================================
-- Function: AutoTurret.OnFreeze
--
-- This function is the event handler for when an AutoTurret
-- when it is hit by a freeze weapon. If single player or 
-- turrets are invulnerable then this function exits without 
-- doing anything. If not then the Item.OnFreeze function is
-- called for the item.
--
-- \param[in] shooterId
-- The ID of the attacker.
--
-- \param[in] weaponId
-- The ID of the weapon used.
--
-- \param[in] value
--
-- =============================================================================
function AutoTurret:OnFreeze(shooterId, weaponId, value)
	if(g_gameRules:IsMultiplayer() and (not XCfgVar or not XCfgVar.useVulnerableTurretsFeature))then
		return false;
	else
		return Item.OnFreeze(self, shooterId, weaponId, value);
	end;
end

-- =============================================================================
-- Function: AutoTurretAA.OnFreeze
--
-- This function is the event handler for when an AutoTurretAA
-- when it is hit by a freeze weapon. If single player or 
-- turrets are invulnerable then this function exits without 
-- doing anything. If not then the Item.OnFreeze function is
-- called for the item.
--
-- \param[in] shooterId
-- The ID of the attacker.
--
-- \param[in] weaponId
-- The ID of the weapon used.
--
-- \param[in] value
--
-- =============================================================================
function AutoTurretAA:OnFreeze(shooterId, weaponId, value)
	if(g_gameRules:IsMultiplayer() and (not XCfgVar or not XCfgVar.useVulnerableTurretsFeature))then
		return false;
	else
		return Item.OnFreeze(self, shooterId, weaponId, value);
	end;
end

----------------------------------------------------------------------------------------------------
AlienTurret.Properties.DamageMultipliers = {
	Bullet = 1.0,
	Explosion = 1.0,
	Collision = 1.0,
	Melee = 1.0,
};

AlienTurret.Properties.GunTurret.bVulnerable=1;

-- =============================================================================
-- Function: AlienTurret.Server:OnHit
--
-- This function is the event handler for when an AlienTurret
-- when it is hit.  
--
-- \param[in] hit
-- Structure containing the parameters for the hit.
-- =============================================================================
function AlienTurret.Server:OnHit(hit)
	if(self.Properties.GunTurret.bVulnerable==0)then
		return;
	end;
	
	local dmg=hit.damage;
	local mul=self.Properties.DamageMultipliers;
	if(hit.type=="bullet")then dmg=dmg*mul.Bullet;end;
	if(hit.type=="collision")then dmg=dmg*mul.Collision;end;
	if(hit.type=="melee")then dmg=dmg*mul.Melee;end;
	if(hit.explosion)then
		dmg=dmg*mul.Explosion;
	end;
	
	hit.damage=dmg;
	
	local explosionOnly=tonumber(self.Properties.bExplosionOnly or 0)~=0;
  local hitpoints = self.Properties.HitPoints;
  
	if (hitpoints and (hitpoints > 0)) then
		local destroyed=self.item:IsDestroyed()
		if (hit.type=="repair") then
			self.item:OnHit(hit);
		elseif ((not explosionOnly) or (hit.explosion)) then
			if ((not g_gameRules:IsMultiplayer()) or g_gameRules.game:GetTeam(hit.shooterId)~=g_gameRules.game:GetTeam(self.id)) then
				self.item:OnHit(hit);
				if (not destroyed) then
					if (hit.damage>0) then
						if (g_gameRules.Server.OnTurretHit) then
							g_gameRules.Server.OnTurretHit(g_gameRules, self, hit);
						end
					end
				
					if (self.item:IsDestroyed()) then
						if(self.FlowEvents and self.FlowEvents.Outputs.Destroyed)then
							self:ActivateOutput("Destroyed",1);
						end
					end
				end
			end
		end
	end
end


----------------------------------------------------------------------------------------------------
--Script.ReloadScript("scripts/entities/items/crosshairs.lua");
--Script.ReloadScript("scripts/entities/items/ui/newweaponui.lua");

